package com.hc.util;

import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class ThreadManager {
    // 存储 id 和锁、条件变量的映射关系
    private final ConcurrentHashMap<String, LockAndCondition> lockMap = new ConcurrentHashMap<>();

    /**
     * 添加线程并阻塞当前线程
     *
     * @param id 线程标识
     */
    public void addAndBlock(String id) {
        // 获取或创建锁和条件变量
        LockAndCondition lockAndCondition = lockMap.computeIfAbsent(id, k -> new LockAndCondition());

        Lock lock = lockAndCondition.lock;
        Condition condition = lockAndCondition.condition;

        lock.lock();
        try {
            // 如果已经有线程在等待，唤醒之前的线程
            if (lockAndCondition.hasThread) {
                condition.signal(); // 唤醒之前的线程
            }

            // 标记当前线程为等待状态
            lockAndCondition.hasThread = true;

            // 阻塞当前线程，最长等待 30 秒
            boolean isTimeout = !condition.await(30, TimeUnit.SECONDS);
            if (isTimeout) {
                System.out.println("Thread timeout for id: " + id);
                lockAndCondition.hasThread = false; // 超时后清除标记
                lockMap.remove(id); // 从 Map 中移除
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("Thread was interrupted", e);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 唤醒指定 id 的线程
     *
     * @param id 线程标识
     */
    public void notifyThread(String id) {
        LockAndCondition lockAndCondition = lockMap.remove(id);
        if (lockAndCondition == null) {
            return;
        }

        Lock lock = lockAndCondition.lock;
        Condition condition = lockAndCondition.condition;

        lock.lock();
        try {
            if (lockAndCondition.hasThread) {
                condition.signal(); // 唤醒线程
                lockAndCondition.hasThread = false; // 清除标记
            }
        } finally {
            lock.unlock();
        }
    }

    /**
     * 内部类：封装锁和条件变量
     */
    private static class LockAndCondition {
        final Lock lock = new ReentrantLock();
        final Condition condition = lock.newCondition();
        boolean hasThread = false; // 标记是否有线程在等待
    }
}